<template>
  <div class="app-container">
    <el-row :gutter="20">
      <el-col :span="24">
        <el-card shadow="hover" class="upload-card">
          <div slot="header" class="card-header">
            <span class="header-title">智能文档处理</span>
          </div>
          <el-upload
            class="upload-demo"
            drag
            action="#"
            :auto-upload="false"
            :on-change="handleFileChange"
            :show-file-list="false"
            accept=".xlsx,.xls,.csv,.doc,.docx,.pdf,.txt,.ppt,.pptx,.md,.jpg,.jpeg,.png,.gif,.zip,.rar,.7z"
          >
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">
              支持格式：Word (.docx), PDF (.pdf), TXT (.txt), Excel (.xlsx,
              .xls), CSV (.csv), PowerPoint (.ppt, .pptx), Markdown (.md), 图片
              (.jpg, .jpeg, .png, .gif), 压缩文件 (.zip, .rar, .7z)等
              文件限制：200MB
            </div>
          </el-upload>
        </el-card>

        <!-- 预览区域 -->
        <el-card v-if="!currentFile" shadow="hover" class="preview-card">
          <div slot="header" class="card-header">
            <span class="header-title">文件预览区</span>
          </div>
          <div class="preview-placeholder">
            <div class="preview-content">
              <i class="el-icon-document"></i>
              <p class="preview-title">请选择或拖拽文件到上方区域</p>
              <p class="preview-tip">
                支持预览的文件类型：Word、PDF、TXT、Excel、图片等
              </p>
            </div>
          </div>
        </el-card>

        <!-- 文件预览和编辑区域 -->
        <el-card v-if="currentFile" shadow="hover" class="preview-card">
          <div slot="header" class="card-header">
            <span class="header-title">文件预览与编辑</span>
            <div class="header-buttons">
              <el-button type="info" @click="handleCancel" size="small">
                <i class="el-icon-close"></i> 取消
              </el-button>
              <el-button
                type="primary"
                @click="handleUpload"
                :loading="loading"
                size="small"
              >
                <i class="el-icon-upload2"></i> 确认上传
              </el-button>
            </div>
          </div>
          <div class="preview-container">
            <!-- 文本文件预览 -->
            <div v-if="isTextFile" class="text-preview">
              <div class="file-info">
                <p>文件名：{{ currentFile.name }}</p>
                <p>大小：{{ formatFileSize(currentFile.size) }}</p>
                <p>类型：{{ fileTypeDisplay }}</p>
              </div>
              <el-input
                type="textarea"
                v-model="textContent"
                :rows="20"
                placeholder="文件内容"
              ></el-input>
            </div>
            <!-- Word文件预览 -->
            <div v-else-if="isWordFile" class="word-preview">
              <div class="file-info">
                <p>文件名：{{ currentFile.name }}</p>
                <p>大小：{{ formatFileSize(currentFile.size) }}</p>
                <p>类型：{{ fileTypeDisplay }}</p>
              </div>
              <div v-if="isOldDocFile">
                <div class="doc-preview-message">
                  <i class="el-icon-warning"></i>
                  <p>旧版Word文件(.doc)暂不支持在线预览</p>
                  <p>建议您将文件转换为.docx格式后再上传</p>
                  <el-button
                    type="primary"
                    size="small"
                    @click="handleDownload"
                  >
                    下载文件
                  </el-button>
                </div>
              </div>
              <div v-else class="word-viewer">
                
                <div
                  class="word-content"
                  contenteditable="false"
                  readonly
                ></div>
              </div>
            </div>
            <!-- Excel文件预览 -->
            <div v-else-if="isExcelFile" class="excel-preview">
              <div class="file-info">
                <p>文件名：{{ currentFile.name }}</p>
                <p>大小：{{ formatFileSize(currentFile.size) }}</p>
                <p>类型：{{ fileTypeDisplay }}</p>
                <p v-if="workbookInfo">工作表：{{ workbookInfo.sheetNames.length }}个，当前：{{ workbookInfo.currentSheet }}</p>
                <p>数据行数：{{ excelData.length }}行，列数：{{ excelColumns.length }}列</p>
              </div>
              
              <!-- 工作表切换 -->
              <div v-if="workbookInfo && workbookInfo.sheetNames.length > 1" class="sheet-selector">
                <span class="sheet-label">工作表：</span>
                <el-select v-model="currentSheetIndex" @change="switchSheet" size="small" style="width: 200px;">
                  <el-option
                    v-for="(sheetName, index) in workbookInfo.sheetNames"
                    :key="index"
                    :label="sheetName"
                    :value="index"
                  ></el-option>
                </el-select>
              </div>
              
              <!-- 数据统计 -->
              <div class="data-stats" v-if="excelData.length > 0">
                <el-tag type="info" size="small">总行数：{{ excelData.length }}</el-tag>
                <el-tag type="success" size="small">总列数：{{ excelColumns.length }}</el-tag>
                <el-tag type="warning" size="small">显示范围：{{ pagination.pageSize * (pagination.currentPage - 1) + 1 }}-{{ Math.min(pagination.pageSize * pagination.currentPage, excelData.length) }}</el-tag>
              </div>
              
              <el-table
                :data="paginatedExcelData"
                border
                style="width: 100%"
                :height="tableHeight"
                :show-header="true"
                :max-height="tableHeight"
                stripe
                highlight-current-row
              >
                <el-table-column
                  v-for="(col, index) in excelColumns"
                  :key="index"
                  :prop="col.prop"
                  :label="String(col.label)"
                  :min-width="120"
                  :show-overflow-tooltip="true"
                >
                  <template slot-scope="scope">
                    <div class="cell-content">
                      {{ formatCellValue(scope.row[col.prop], col.type) }}
                    </div>
                  </template>
                </el-table-column>
              </el-table>
              
              <!-- 分页器 -->
              <div class="pagination-container">
                <el-pagination
                  @size-change="handleSizeChange"
                  @current-change="handleCurrentChange"
                  :current-page="pagination.currentPage"
                  :page-sizes="[50, 100, 200, 500, 1000]"
                  :page-size="pagination.pageSize"
                  layout="total, sizes, prev, pager, next, jumper"
                  :total="excelData.length"
                >
                </el-pagination>
              </div>
            </div>
            <!-- 图片文件预览 -->
            <div v-else-if="isImageFile" class="image-preview">
              <div class="image-container">
                <img :src="previewUrl" alt="预览图片" class="preview-image" />
                <div class="image-info">
                  <p>文件名：{{ currentFile.name }}</p>
                  <p>大小：{{ formatFileSize(currentFile.size) }}</p>
                  <p>类型：{{ fileTypeDisplay }}</p>
                </div>
              </div>
            </div>
            <!-- PDF文件预览 -->
            <div v-else-if="isPdfFile" class="pdf-preview">
              <div class="file-info">
                <p>文件名：{{ currentFile.name }}</p>
                <p>大小：{{ formatFileSize(currentFile.size) }}</p>
                <p>类型：{{ fileTypeDisplay }}</p>
              </div>
              <iframe :src="previewUrl" width="100%" height="500px"></iframe>
            </div>
            <!-- PPT文件预览 -->
            <div v-else-if="isPptFile" class="ppt-preview">
              <div class="file-info">
                <p>文件名：{{ currentFile.name }}</p>
                <p>大小：{{ formatFileSize(currentFile.size) }}</p>
                <p>类型：{{ fileTypeDisplay }}</p>
              </div>
              <p>PPT文件暂不支持在线预览和编辑，请下载后查看</p>
              <el-button type="primary" @click="handleDownload"
                >下载文件</el-button
              >
            </div>
            <!-- Markdown文件预览 -->
            <div v-else-if="isMarkdownFile" class="markdown-preview">
              <div class="file-info">
                <p>文件名：{{ currentFile.name }}</p>
                <p>大小：{{ formatFileSize(currentFile.size) }}</p>
                <p>类型：{{ fileTypeDisplay }}</p>
              </div>
              <p>Markdown文件暂不支持在线预览和编辑</p>
            </div>
            <!-- 其他文件类型预览 -->
            <div v-else class="other-preview">
              <div class="file-info">
                <p>文件名：{{ currentFile.name }}</p>
                <p>大小：{{ formatFileSize(currentFile.size) }}</p>
                <p>类型：{{ fileTypeDisplay }}</p>
              </div>
              <p>该文件类型暂不支持预览和编辑</p>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 使用数据清洗对话框组件 -->
    <data-cleaning-dialog
      :visible.sync="cleaningStatus.visible"
      :cleanStatus="cleaningStatus.status"
      :message="cleaningStatus.message"
      :progress="cleaningStatus.progress"
      :errors="cleaningStatus.errors"
    />
  </div>
</template>

<script>
import request from "@/utils/request";
import mammoth from "mammoth";
import * as XLSX from "xlsx";
import DataCleaningDialog from "@/components/DataClean/DataCleaningDialog.vue";

export default {
  name: "DataCleaning",
  components: {
    DataCleaningDialog,
  },
  mounted() {
    // 监听窗口大小变化
    window.addEventListener('resize', this.handleResize);
  },
  beforeDestroy() {
    // 移除监听器
    window.removeEventListener('resize', this.handleResize);
  },
  data() {
    return {
      loading: false,

      cleanRule: "",
      currentFile: null,
      previewUrl: "",
      previewType: "",
      textContent: "",
      excelData: [],
      excelColumns: [],
      workbookInfo: null,
      currentSheetIndex: 0,
      pagination: {
        currentPage: 1,
        pageSize: 100,
      },

      cleaningStatus: {
        visible: false,
        status: "processing",
        message: "",
        errors: [],
        progress: 0,
      },

    };
  },
  computed: {
    isTextFile() {
      return [".txt", ".md"].includes(this.previewType);
    },
    isCsvFile() {
      return this.previewType.toLowerCase() === ".csv";
    },
    isWordFile() {
      return [".doc", ".docx"].includes(this.previewType.toLowerCase());
    },
    isDocxFile() {
      return this.previewType.toLowerCase() === ".docx";
    },
    isOldDocFile() {
      return this.previewType.toLowerCase() === ".doc";
    },
    isExcelFile() {
      return [".xls", ".xlsx", ".csv"].includes(this.previewType.toLowerCase());
    },
    isImageFile() {
      return [".jpg", ".jpeg", ".png", ".gif"].includes(
        this.previewType.toLowerCase()
      );
    },
    isCompressedFile() {
      return [".zip", ".rar", ".7z"].includes(this.previewType.toLowerCase());
    },
    isPdfFile() {
      return this.previewType.toLowerCase() === ".pdf";
    },
    isPptFile() {
      return [".ppt", ".pptx"].includes(this.previewType.toLowerCase());
    },
    isMarkdownFile() {
      return this.previewType.toLowerCase() === ".md";
    },
    getStatusIcon() {
      switch (this.cleaningStatus.status) {
        case "success":
          return "el-icon-success";
        case "error":
          return "el-icon-error";
        default:
          return "el-icon-loading";
      }
    },
    fileTypeDisplay() {
      if (!this.previewType) return "";

      const typeMap = {
        ".doc": "Word文档",
        ".docx": "Word文档",
        ".xls": "Excel表格",
        ".xlsx": "Excel表格",
        ".csv": "CSV表格",
        ".pdf": "PDF文档",
        ".txt": "文本文件",
        ".ppt": "PowerPoint演示文稿",
        ".pptx": "PowerPoint演示文稿",
        ".md": "Markdown文档",
        ".jpg": "JPEG图片",
        ".jpeg": "JPEG图片",
        ".png": "PNG图片",
        ".gif": "GIF图片",
        ".zip": "ZIP压缩包",
        ".rar": "RAR压缩包",
        ".7z": "7Z压缩包",
      };

      return typeMap[this.previewType.toLowerCase()] || "未知类型";
    },
    paginatedExcelData() {
      const start = (this.pagination.currentPage - 1) * this.pagination.pageSize;
      const end = start + this.pagination.pageSize;
      return this.excelData.slice(start, end);
    },
    tableHeight() {
      // 动态计算表格高度，留出空间给分页器和统计信息
      return Math.max(400, window.innerHeight - 600);
    },
  },
  methods: {
    async handleFileChange(file) {
      if (!file) return;

      this.currentFile = file;
      this.previewType = "." + file.name.split(".").pop().toLowerCase();

      try {
        if (this.isTextFile) {
          // 处理文本文件
          const reader = new FileReader();
          reader.onload = (e) => {
            this.textContent = e.target.result;
            if (this.isMarkdownFile) {
              this.$nextTick(() => {
                const viewer = document.querySelector(".word-content");
                if (viewer) {
                  viewer.innerHTML = this.textContent;
                }
              });
            }
          };
          reader.readAsText(file.raw);
        } else if (this.isImageFile) {
          // 处理图片文件预览
          try {
            this.previewUrl = URL.createObjectURL(file.raw);
          } catch (imageError) {
            this.$message.error("图片处理失败: " + imageError.message);
          }
        } else if (this.isPptFile) {
          // 对于PPT文件，目前只提供下载功能
          this.previewUrl = URL.createObjectURL(file.raw);
          this.$message.warning("PPT文件暂不支持在线预览和编辑，请下载后查看");
        } else if (this.isWordFile) {
          try {
            if (this.isOldDocFile) {
              // 对于旧版.doc文件，尝试使用后端API解析
              this.$message.info("正在解析.doc文件，请稍候...");
              const formData = new FormData();
              formData.append("file", file.raw);
              
              const response = await request({
                url: "/api/v1/rag/parse_document",
                method: "post",
                data: formData,
                headers: {
                  "Content-Type": "multipart/form-data",
                },
              });
              
              if (response.code === "0000" && response.data) {
                this.$nextTick(() => {
                  const viewer = document.querySelector(".word-content");
                  if (viewer) {
                    viewer.innerHTML = response.data.replace(/\n/g, '<br>');
                  }
                });
              } else {
                this.$message.warning("旧版Word文件(.doc)暂不支持在线预览和编辑，请转换为.docx格式");
                this.previewUrl = URL.createObjectURL(file.raw);
              }
            } else {
              // 处理.docx文件
              const arrayBuffer = await this.readFileAsArrayBuffer(file.raw);
              const result = await mammoth.convertToHtml({ arrayBuffer });

              if (result.value) {
                this.$nextTick(() => {
                  const viewer = document.querySelector(".word-content");
                  if (viewer) {
                    viewer.innerHTML = result.value;
                  }
                });
              } else {
                throw new Error("Word转换结果为空");
              }
            }
          } catch (wordError) {
            this.$message.error("Word文件处理失败: " + wordError.message);
          }
        } else if (this.isExcelFile) {
          try {
            // 处理Excel文件
            const arrayBuffer = await this.readFileAsArrayBuffer(file.raw);

            const workbook = XLSX.read(arrayBuffer, { type: "array" });

            if (!workbook.SheetNames || workbook.SheetNames.length === 0) {
              throw new Error("Excel文件没有工作表");
            }

            // 保存工作簿信息
            this.workbookInfo = {
              sheetNames: workbook.SheetNames,
              currentSheet: workbook.SheetNames[0],
              workbook: workbook
            };
            this.currentSheetIndex = 0;

            // 处理第一个工作表
            await this.processWorksheet(workbook.SheetNames[0], workbook.Sheets[workbook.SheetNames[0]]);
            
          } catch (excelError) {
            this.$message.error("Excel文件处理失败: " + excelError.message);
          }
        } else if (this.isPdfFile) {
          try {
            // PDF文件直接使用预览URL
            this.previewUrl = URL.createObjectURL(file.raw);
          } catch (pdfError) {
            this.$message.error("PDF文件处理失败: " + pdfError.message);
          }
        } else {
          this.$message.warning("不支持的文件类型: " + this.previewType);
        }
      } catch (error) {
        this.$message.error("文件预览失败: " + error.message);
      }
    },

    readFileAsArrayBuffer(file) {
      return new Promise((resolve, reject) => {
        try {
          const reader = new FileReader();
          reader.onload = (e) => {
            resolve(e.target.result);
          };
          reader.onerror = (e) => {
            reject(new Error("文件读取失败"));
          };
          reader.readAsArrayBuffer(file);
        } catch (error) {
          reject(new Error("文件读取器创建失败"));
        }
      });
    },

    async handleUpload() {
      if (!this.currentFile) return;

      // 检查文件大小
      const maxSize = 200 * 1024 * 1024; // 200MB
      if (this.currentFile.size > maxSize) {
        this.$message.error("文件大小不能超过200MB");
        return;
      }

      // 检查文件类型
      const allowedTypes = [
        ".xlsx",
        ".xls",
        ".csv",
        ".doc",
        ".docx",
        ".pdf",
        ".txt",
        ".ppt",
        ".pptx",
        ".md",
        ".jpg",
        ".jpeg",
        ".png",
        ".gif",
        ".zip",
        ".rar",
        ".7z",
      ];
      const fileExtension = this.currentFile.name
        .substring(this.currentFile.name.lastIndexOf("."))
        .toLowerCase();
      if (!allowedTypes.includes(fileExtension)) {
        this.$message.error("不支持的文件类型");
        return;
      }

      this.loading = true;

      try {
        const formData = new FormData();

        // 根据文件类型处理上传数据
        if (this.isTextFile && this.textContent) {
          const blob = new Blob([this.textContent], { type: "text/plain" });
          formData.append("file", blob, this.currentFile.name);
        } else if (this.isWordFile) {
          // 对于Word文件，直接使用原始文件
          formData.append("file", this.currentFile.raw);
        } else {
          // 直接使用原始文件
          formData.append("file", this.currentFile.raw);
        }

        // 如果是图片文件、PDF文件、压缩文件或PPT文件，直接上传不显示清洗过程
        if (this.isImageFile || this.isPdfFile || this.isCompressedFile || this.isPptFile) {
          let response;
          try {
            response = await request({
              url: "/system/oss/upload",
              method: "post",
              data: formData,
              headers: {
                "Content-Type": "multipart/form-data",
              },
              timeout: 30000, // 30秒超时
            });
          } catch (error) {
            if (error.code === 'ECONNABORTED' || (error.message && error.message.includes('timeout'))) {
              this.$message.error("超时，请检查文档后重试");
            } else {
              this.$message.error("文件上传失败：" + (error.message || "未知错误"));
            }
            this.loading = false;
            return;
          }

          if (response.code === 200) {
            this.$message.success("文件上传成功");
            // 清理预览URL
            if (this.previewUrl) {
              URL.revokeObjectURL(this.previewUrl);
            }
            // 重置状态
            this.currentFile = null;
            this.previewUrl = "";
          } else {
            this.$message.error(response.msg || "文件上传失败");
          }
          this.loading = false;
          return;
        }

        // 非图片、PDF、压缩包、PPT文件显示数据清洗对话框
        this.cleaningStatus = {
          visible: true,
          status: "processing",
          message: "正在开始数据清洗...",
          errors: [],
          progress: 0,
        };

        this.cleaningStatus.message = "正在分析文件...";
        this.cleaningStatus.progress = 20;

        let response;
        try {
          response = await request({
            url: "/system/oss/upload",
            method: "post",
            data: formData,
            headers: {
              "Content-Type": "multipart/form-data",
            },
            timeout: 30000, // 30秒超时
          });
        } catch (error) {
          if (error.code === 'ECONNABORTED' || (error.message && error.message.includes('timeout'))) {
            this.cleaningStatus.status = "error";
            this.cleaningStatus.message = "超时，请检查文档后重试";
            this.$message.error("超时，请检查文档后重试");
          } else {
            this.cleaningStatus.status = "error";
            this.cleaningStatus.message = error.message || "文件上传失败";
            if (!error.message.includes("数据文件中的错误数量过多")) {
              this.$message.error(
                "文件上传失败：" + (error.message || "未知错误")
              );
            }
          }
          this.loading = false;
          setTimeout(() => {
            this.cleaningStatus.visible = false;
          }, 3000);
          return;
        }

        this.cleaningStatus.progress = 80;

        if (response.code === 200) {
          if (response.data && response.data.cleaningResult) {
            const cleaningResult = response.data.cleaningResult;
            if (cleaningResult.status === "error") {
              this.cleaningStatus.status = "error";
              this.cleaningStatus.message = cleaningResult.message;
              this.cleaningStatus.errors = cleaningResult.errors || [];
              this.$message.error(cleaningResult.message);
              this.loading = false;
              return;
            } else if (cleaningResult.status === "success") {
              this.cleaningStatus.status = "success";
              this.cleaningStatus.message = "数据清洗成功，文件上传完成";
              this.cleaningStatus.progress = 100;
              this.$message.success("文件上传成功");
            }
          }

          // 清理预览URL
          if (this.previewUrl) {
            URL.revokeObjectURL(this.previewUrl);
          }
          // 重置状态
          this.currentFile = null;
          this.previewUrl = "";
          this.textContent = "";
          this.excelData = [];
          this.excelColumns = [];
          this.workbookInfo = null;
          this.currentSheetIndex = 0;
          this.pagination = {
            currentPage: 1,
            pageSize: 100,
          };
        } else {
          this.cleaningStatus.status = "error";
          this.cleaningStatus.message = response.msg || "文件上传失败";
          this.$message.error(response.msg || "文件上传失败");
        }
      } catch (error) {
        if (this.isImageFile || this.isPdfFile || this.isPptFile) {
          this.$message.error("文件上传失败：" + (error.message || "未知错误"));
        } else {
          this.cleaningStatus.status = "error";
          this.cleaningStatus.message = error.message || "文件上传失败";
          if (!error.message.includes("数据文件中的错误数量过多")) {
            this.$message.error(
              "文件上传失败：" + (error.message || "未知错误")
            );
          }
        }
      } finally {
        this.loading = false;
        if (!this.isImageFile && !this.isPdfFile && !this.isPptFile) {
          // 3秒后自动关闭清洗状态对话框
          setTimeout(() => {
            this.cleaningStatus.visible = false;
          }, 3000);
        }
      }
    },

    handleCancel() {
      // 清理预览URL
      if (this.previewUrl) {
        URL.revokeObjectURL(this.previewUrl);
      }
      // 重置状态
      this.currentFile = null;
      this.previewUrl = "";
      this.textContent = "";
      this.excelData = [];
      this.excelColumns = [];
      this.workbookInfo = null;
      this.currentSheetIndex = 0;
      this.pagination = {
        currentPage: 1,
        pageSize: 100,
      };
      this.cleaningStatus.status = "processing";
      this.$message.info("已取消文件上传");
    },







    formatCellValue(value, type) {
      if (value === null || value === undefined) {
        return "";
      }
      
      // 处理日期类型
      if (value instanceof Date) {
        return value.toLocaleDateString('zh-CN');
      }
      
      // 处理数字类型
      if (typeof value === 'number') {
        // 如果是整数
        if (Number.isInteger(value)) {
          return value.toString();
        }
        // 如果是小数，保留2位小数
        return value.toFixed(2);
      }
      
      // 处理布尔类型
      if (typeof value === 'boolean') {
        return value ? '是' : '否';
      }
      
      // 处理字符串类型，去除多余空格
      if (typeof value === 'string') {
        return value.trim();
      }
      
      // 其他类型转换为字符串
      return String(value);
    },

    handleDownload() {
      if (this.previewUrl) {
        const link = document.createElement("a");
        link.href = this.previewUrl;
        link.download = this.currentFile.name;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      }
    },



    formatFileSize(size) {
      if (size < 1024) {
        return size + " B";
      } else if (size < 1024 * 1024) {
        return (size / 1024).toFixed(2) + " KB";
      } else if (size < 1024 * 1024 * 1024) {
        return (size / (1024 * 1024)).toFixed(2) + " MB";
      } else {
        return (size / (1024 * 1024 * 1024)).toFixed(2) + " GB";
      }
    },
    
    // Excel相关方法
    async processWorksheet(sheetName, worksheet) {
      try {
        // 转换为JSON数据
        const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });

        if (jsonData.length === 0) {
          throw new Error("工作表没有数据");
        }

        // 设置表头
        this.excelColumns = jsonData[0].map((header, index) => ({
          prop: `col${index}`,
          label: header || `列${index + 1}`,
        }));

        // 设置数据
        this.excelData = jsonData.slice(1).map((row) => {
          const obj = {};
          row.forEach((cell, index) => {
            obj[`col${index}`] = cell;
          });
          return obj;
        });

        // 重置分页
        this.pagination.currentPage = 1;
        
        // 更新当前工作表信息
        if (this.workbookInfo) {
          this.workbookInfo.currentSheet = sheetName;
        }
        
      } catch (error) {
        this.$message.error(`处理工作表 ${sheetName} 失败: ${error.message}`);
      }
    },

    async switchSheet(sheetIndex) {
      if (!this.workbookInfo || !this.workbookInfo.workbook) {
        return;
      }
      
      const sheetName = this.workbookInfo.sheetNames[sheetIndex];
      const worksheet = this.workbookInfo.workbook.Sheets[sheetName];
      
      if (worksheet) {
        await this.processWorksheet(sheetName, worksheet);
      }
    },

    handleSizeChange(size) {
      this.pagination.pageSize = size;
      this.pagination.currentPage = 1;
    },

    handleCurrentChange(page) {
      this.pagination.currentPage = page;
    },

    handleResize() {
      // 触发计算属性重新计算
      this.$forceUpdate();
    },


  },
};
</script>

<style scoped>
.app-container {
  padding: 20px;
  background-color: #f5f7fa;
  min-height: 100vh;
}

.upload-card {
  margin-bottom: 20px;
  border-radius: 8px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px 20px;
}

.header-title {
  font-size: 18px;
  font-weight: 600;
  color: #303133;
}

.header-buttons {
  display: flex;
  gap: 10px;
}

.upload-demo {
  text-align: center;
  padding: 20px;
}

.el-upload-dragger {
  width: 100%;
  height: 200px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  border: 2px dashed #409eff;
  border-radius: 12px;
  background-color: #f5f7fa;
  transition: all 0.3s;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
}

.el-upload-dragger:hover {
  border-color: #66b1ff;
  background-color: #ecf5ff;
  transform: translateY(-2px);
  box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.1);
}

.el-upload__text {
  color: #606266;
  font-size: 14px;
  margin-top: 15px;
  line-height: 1.8;
  padding: 0 20px;
  text-align: center;
  max-width: 600px;
}

.el-icon-upload {
  font-size: 48px;
  color: #409eff;
  margin-bottom: 10px;
}

.el-upload-dragger .el-icon-upload {
  margin: 0 0 15px;
  font-size: 48px;
  color: #409eff;
  transition: all 0.3s;
}

.el-upload-dragger:hover .el-icon-upload {
  transform: scale(1.1);
  color: #66b1ff;
}

.preview-card {
  margin-top: 20px;
  border-radius: 8px;
  background: linear-gradient(to bottom, #ffffff, #f8f9fa);
  border: none;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
  min-height: calc(100vh - 400px);
}

.preview-container {
  min-height: calc(100vh - 450px);
  padding: 20px;
}

.text-preview {
  width: 100%;
}

.text-preview .el-textarea__inner {
  min-height: calc(100vh - 500px) !important;
  font-size: 14px;
  line-height: 1.6;
  border-radius: 4px;
}

.word-preview {
  padding: 20px;
  background: #fff;
  border: 1px solid #dcdfe6;
  border-radius: 8px;
  min-height: calc(100vh - 450px);
  overflow-y: auto;
}

.word-viewer {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.viewer-header {
  padding: 15px;
  background: linear-gradient(135deg, #f5f7fa 0%, #e4e7ed 100%);
  border-radius: 8px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: 1px solid #dcdfe6;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.word-content {
  line-height: 1.8;
  font-size: 14px;
  color: #333;
  padding: 30px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  min-height: calc(100vh - 500px);
  outline: none;
  border: 1px solid #e4e7ed;
  transition: all 0.3s ease;
  font-family: 'Microsoft YaHei', 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
  user-select: text;
  cursor: text;
}

.word-content[contenteditable="false"] {
  background-color: #fafafa;
  border: 1px solid #e4e7ed;
  cursor: default;
}

.word-content[contenteditable="false"]:focus {
  border: 1px solid #e4e7ed;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.word-content p {
  margin: 10px 0;
}

.word-content h1, .word-content h2, .word-content h3, 
.word-content h4, .word-content h5, .word-content h6 {
  margin: 20px 0 10px 0;
  font-weight: 600;
}

.word-content ul, .word-content ol {
  margin: 10px 0;
  padding-left: 20px;
}

.word-content table {
  border-collapse: collapse;
  width: 100%;
  margin: 15px 0;
}

.word-content th, .word-content td {
  border: 1px solid #dcdfe6;
  padding: 8px 12px;
  text-align: left;
}

.word-content th {
  background-color: #f5f7fa;
  font-weight: 600;
}

.excel-preview {
  width: 100%;
  overflow-x: auto;
}

.sheet-selector {
  margin: 15px 0;
  padding: 10px;
  background: #f5f7fa;
  border-radius: 8px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.sheet-label {
  font-weight: 500;
  color: #606266;
}

.data-stats {
  margin: 15px 0;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.excel-preview .el-table {
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.excel-preview .el-table__body-wrapper {
  max-height: none;
}

.pagination-container {
  margin-top: 20px;
  display: flex;
  justify-content: center;
  padding: 15px;
  background: #f5f7fa;
  border-radius: 8px;
}

.cell-content {
  padding: 8px;
  text-align: left;
  word-break: break-word;
  white-space: pre-wrap;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.image-preview {
  text-align: center;
  padding: 20px;
}

.image-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  background: #fff;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.preview-image {
  max-width: 100%;
  max-height: calc(100vh - 500px);
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.image-info {
  text-align: left;
  padding: 15px;
  background: #f5f7fa;
  border-radius: 4px;
  width: 100%;
}

.image-info p {
  margin: 5px 0;
  color: #606266;
}

.pdf-preview {
  width: 100%;
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
}

.pdf-preview iframe {
  width: 100%;
  height: calc(100vh - 450px);
  border: none;
  border-radius: 4px;
}

.ppt-preview {
  text-align: center;
  padding: 40px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.markdown-preview {
  text-align: center;
  padding: 40px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.doc-preview-message {
  text-align: center;
  padding: 40px;
  background: #fff;
  border: 1px solid #dcdfe6;
  border-radius: 8px;
}

.doc-preview-message i {
  font-size: 48px;
  color: #e6a23c;
  margin-bottom: 20px;
}

.doc-preview-message p {
  margin: 10px 0;
  color: #606266;
}

.cleaning-status {
  padding: 20px;
}

.cleaning-progress {
  margin: 20px 0;
}

.cleaning-message {
  display: flex;
  align-items: center;
  margin: 20px 0;
  padding: 15px;
  border-radius: 8px;
}

.cleaning-message i {
  margin-right: 10px;
  font-size: 20px;
}

.cleaning-message.processing {
  background-color: #e6f7ff;
  color: #1890ff;
}

.cleaning-message.success {
  background-color: #f6ffed;
  color: #52c41a;
}

.cleaning-message.error {
  background-color: #fff2f0;
  color: #f5222d;
}

.cleaning-errors {
  margin-top: 20px;
  border: 1px solid #f5f5f5;
  border-radius: 8px;
  padding: 15px;
}

.error-title {
  font-weight: bold;
  margin-bottom: 10px;
  color: #f5222d;
}

.cleaning-errors ul {
  margin: 0;
  padding-left: 20px;
}

.cleaning-errors li {
  color: #666;
  margin-bottom: 5px;
}

.file-info {
  margin-bottom: 15px;
  padding: 10px;
  background: #f5f7fa;
  border-radius: 4px;
}

.file-info p {
  margin: 5px 0;
  color: #606266;
  font-size: 14px;
}

.preview-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: calc(100vh - 450px);
  background: linear-gradient(135deg, #f5f7fa 0%, #f8f9fa 100%);
  border-radius: 8px;
  padding: 40px;
  text-align: center;
  position: relative;
  overflow: hidden;
}

.preview-placeholder::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(90deg, #409eff, #67c23a);
  opacity: 0.1;
}

.preview-content {
  position: relative;
  z-index: 1;
  padding: 40px;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 12px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
  transition: all 0.3s ease;
}

.preview-content:hover {
  transform: translateY(-5px);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
}

.preview-placeholder i {
  font-size: 72px;
  color: #409eff;
  margin-bottom: 24px;
  opacity: 0.8;
  transition: all 0.3s ease;
}

.preview-content:hover i {
  transform: scale(1.1);
  opacity: 1;
}

.preview-title {
  font-size: 18px;
  color: #303133;
  margin: 16px 0;
  font-weight: 500;
}

.preview-tip {
  font-size: 14px;
  color: #909399;
  margin-top: 16px;
  line-height: 1.6;
  max-width: 400px;
}

.card-header {
  background: transparent;
  border-bottom: 1px solid #ebeef5;
  padding: 16px 20px;
}

.header-title {
  font-size: 16px;
  font-weight: 500;
  color: #303133;
}
</style>
